/* 
 * 		genetik - Genetic Kernel Library 
 *
 * Copyright (C) 2006 Alessandro Bahgat Shehata, Daniele Castagna
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Alessandro Bahgat Shehata - ale (DOT) bahgat (AT) gmail (DOT) com
 * Daniele Castagna - daniele (DOT) castagna (AT) gmail (DOT) com
 * 
 */

/*! 
@file src/EvolutionaryAlgorithm.h
 */

#ifndef GENETIK_EVOLUTIONARYALGORITHM
#define GENETIK_EVOLUTIONARYALGORITHM

namespace genetiK
{

class StopCriterion;
class Population;
class IndividualFactory;
class SelectionMethod;

/*! @brief EvolutionaryAlgorithm: The main evolutionary algorithm.
This class represents the main evolutionary algorithm.
@ingroup genetiK
 */
class EvolutionaryAlgorithm
{

protected:
	/*! @brief Specifies a criterion to stop the EvolutionaryAlgorithm
	*/
        StopCriterion*							stopCriterion;
	/*! @brief Contains the individuals generated by this Algorithm at the present generation
	*/
        Population*							population;
	/*! @brief The Factory that is used to create specific Invidual objects

	This class should be user supplied to create the desired type of Inviduals.
	*/
        IndividualFactory*						individualFactory;

	/*! @brief Provides a scheme to select individuals for crossover and reproduction
	*/
        SelectionMethod*						selectionMethod;

	/*! @brief The size of the Population of Individuals at each generation
	*/
        unsigned int							populationSize;

	/*! @brief Probability to perform crossover for a couple of Individuals
	*/
        double								crossOverProbabilty;

	/*! @brief Probability to perform mutation on an Individual
	*/
        double								mutationProbabilty;

	/*! @brief Specifies if the current EvolutionaryAlgorithm should be elitist

	If elitism is applied, the best Individual in each generation alway survives, unmodified, in the next one.
	*/
        bool								elitism;

public:

	 /*!
	@param populationSize size of the population
	@param factory the individual factory, redefine yours to generate your own Individual.
	@param stopCriterion this class decides the end of the algortihm.
	@param selectionMethod the selection method, if you don't specify it, the default RouletteWheel will be used. The genetiK library has genetiK::RouletteWheel, genetiK::TournamentSelection and RankingSelection. 
	@param mutationProbability 0.01 by default.
	@param crossOverProbability 0.7 by default.
	@param elitism if this is true, the best individual of the current generation will be copied to the next one.
	@see Version 
	  */
        EvolutionaryAlgorithm(const unsigned int populationSize,IndividualFactory* factory,
                           StopCriterion* stopCriterion=NULL,SelectionMethod* selectionMethod = NULL,
			   const double mutationProbability = 0.01,const double crossOverProbability = 0.7,
			   const bool elitism=true);
        virtual ~EvolutionaryAlgorithm(void);

	/*!
	Call this method to start the algorithm. 
	@return return 0 if it's all ok.
	*/
	virtual int							run();
	
	/*!
	Usually this method is called by .run(), but if you want more control on the evolution, you can manually call this before evolve()
	@return return 0 if it's all ok.
	 */	
        virtual int							generatePopulation();
 	/*!
	Usually this method is called by .run(), but if you want more control on the evolution, you can manually call this after generatePopulation()
	@throw IllegalStateException An IllegalStateException is thrown if a call to evolve() is made without having previously called generatePopulation()
	@return return 0 if it's all ok.
	 */	
	virtual int							evolve();
	/*!
	This method is used to access the population at current generation
	@return return the population itself.
	 */	
	virtual Population*						getPopulation() const { return population; };

};

}

#endif
